/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Font parameters.
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#define HUD_FONT_CC 1
#include <utility>
#include <fstream>
#include "base/module.hh"
#include "base/conf.hh"
#include "base/stream.hh"
using namespace base;
#include "hud/module.hh"
#include "hud/font.hh"

namespace hud {

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////  configuration  //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * Compute pathname of font (depends on configuration/installation).
 *****************************************************************************/
INTERN string
ComputeFontPathName( const string& fontName )
{
    // Assume .ttf suffix.
    return base::GetDataDir() + string("/fonts/") + fontName + string(".ttf");
}

////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////  Font  //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * ctor/dtor.
 *****************************************************************************/
Font::Font( const string& name, const fp size,
            const fp widthRatio, const fp heightRatio, const string& pathName )
:   mName(name),
    mSize(size),
    mWidthRatio(widthRatio),
    mHeightRatio(heightRatio),
    mPathName(pathName)
{
ASSERT( not name.empty() );
ASSERT( size > 0 );
ASSERT( widthRatio > 0 );
ASSERT( heightRatio > 0 );
ASSERT( not pathName.empty() );

    // NOP
}

Font::~Font()
{
    // NOP
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////  FontMap  /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

FontMap* FontMap::msInstance;

/*****************************************************************************
 * ctor/dtor.
 *****************************************************************************/
FontMap::FontMap( void )
:   mFontMap(),
    mDefaultFontName()
{
    // NOP
}

FontMap::~FontMap()
{
    // NOP
}

/*****************************************************************************
 * Get font in font map.
 *****************************************************************************/
Font
FontMap::GetFont( const string& fontName ) const
{
    // Actually accepts empty string to mean default font,
    // but clients should explicitly use GetDefaultFont().
    FontMapType::const_iterator iter = mFontMap.find( (not fontName.empty())
                                                      ? fontName : mDefaultFontName );
    if ( UX ( iter == mFontMap.end() ) )
        throw( "FontMap: font is not configured" );
    return iter->second;
}

/*****************************************************************************
 * Get default font in font map.
 *****************************************************************************/
Font
FontMap::GetDefaultFont( void ) const
{
ASSERT( not mDefaultFontName.empty() );

    return GetFont( mDefaultFontName );
}

/*****************************************************************************
 * Parse font from .conf file via C++ stream.
 * @pre Field with "font" keyword was already read from stream.
 *****************************************************************************/
bool
FontMap::ParseFont( std::ifstream& conf )
{
    // Format of line in .conf file:
    // font fontName defaultSize widthRatio heightRatio
    // font  arial  28.0  0.593  1.0

    // Parse and fill font fields.
    // Field with "font" keyword was already read from stream.
    string fontName;               conf >> fontName;
    fp     fontSize        = 0.0f; conf >> fontSize;
    fp     fontWidthRatio  = 0.0f; conf >> fontWidthRatio;
    fp     fontHeightRatio = 0.0f; conf >> fontHeightRatio;

    // Bad stream or Font?
    if ( conf.good()
     and (not fontName.empty())
     and (fontSize > 0.0f)
     and (fontWidthRatio > 0.0f)
     and (fontHeightRatio > 0.0f) )
    {
        // The default font is the first font listed in the configuration.
        if ( mDefaultFontName.empty() )
            mDefaultFontName = fontName;

        // Map font name with Font object.
        mFontMap.insert( std::make_pair( fontName,
                                                      Font( fontName, fontSize,
                                                            fontWidthRatio, fontHeightRatio,
                                                             ComputeFontPathName( fontName ) ) ) );
        return true;
    }
    else
    {
        CERROR << "ERROR: font " << fontName << " mis-configured" << std::endl;
        ASSERT(false);
        return false;
    }
}

} // namespace hud
